﻿using System;
using System.Runtime.InteropServices;

namespace MemHack.Mem
{
	public static class NativeCall
	{
		// 加载动态库
		[DllImport("kernel32.dll")]
		public static extern IntPtr LoadLibrary(string dllToLoad);

		[DllImport("kernel32.dll")]
		public static extern bool IsWow64Process(IntPtr process, out bool wow64Process);

		// 从指定内存中读取字节集数据
		[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
		public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, IntPtr lpNumberOfBytesRead);

		// 从指定内存中写入字节集数据
		[DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
		public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten);

		// 获取进程已分配的虚拟内存信息
		[DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")]
		public static extern uint VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out PMEMORY_BASIC_INFORMATION32 info, uint info_size);

		/// <summary>
		/// 在指定进程中申请一片内存空间
		/// </summary>
		/// <param name="hwnd">进程句柄</param>
		/// <param name="lpaddress">0</param>
		/// <param name="size">要分配的内存大小</param>
		/// <param name="type">MEM_TYPE类型</param>
		/// <param name="tect">PAGE_PROTECT类型</param>
		/// <returns>申请到的空间的地址</returns>
		[DllImport("kernel32.dll")]
		public static extern IntPtr VirtualAllocEx(IntPtr hwnd, IntPtr lpaddress, uint size, uint type, uint protect);

		// 释放指定的虚拟内存空间，size必须为0
		[DllImport("kernel32.dll")]
		public static extern bool VirtualFreeEx(IntPtr hwnd, IntPtr addr, uint size, uint dwFreeType);

		/// <summary>
		/// 获取一个函数在一个模块中的地址
		/// </summary>
		/// <param name="hwnd">模块句柄</param>
		/// <param name="lpname">函数名</param>
		/// <returns></returns>
		[DllImport("kernel32.dll")]
		public static extern IntPtr GetProcAddress(IntPtr hwnd, string lpname);

		/// <summary>
		/// 获取已加载的一个模块的句柄
		/// </summary>
		/// <param name="name">模块名</param>
		/// <returns>模块句柄</returns>
		[DllImport("kernel32.dll")]
		public static extern int GetModuleHandleA(string name);

		/// <summary>
		/// 创建远程线程，也就是在别的进程注入自己的方法并执行
		/// </summary>
		/// <param name="hwnd">进程句柄</param>
		/// <param name="attrib">0</param>
		/// <param name="size">0</param>
		/// <param name="address">指定执行的函数地址</param>
		/// <param name="lpParameter">该函数的参数的地址</param>
		/// <param name="flags">0</param>
		/// <param name="threadid">0</param>
		/// <returns></returns>
		[DllImport("kernel32.dll")]
		public static extern int CreateRemoteThread(IntPtr hwnd, int attrib, int size, IntPtr address, IntPtr lpParameter, int flags, int threadid);

		/// <summary>
		/// 关闭一个应用程序的句柄
		/// </summary>
		/// <param name="handle">句柄</param>
		/// <returns>是否成功</returns>
		[DllImport("kernel32.dll")]
		public static extern int CloseHandle(IntPtr handle);
	}

	[StructLayout(LayoutKind.Sequential)]
	public struct PMEMORY_BASIC_INFORMATION32
	{
		public IntPtr BaseAddress;
		public IntPtr AllocationBase;
		public uint AllocationProtect;
		public uint RegionSize;
		public uint State;
		public uint Protect;
		public uint Type;
	}

	public enum MEM_TYPE : uint
	{
		MEM_COMMIT	     = 0x00001000,
		MEM_RESERVE      = 0x00002000,
		MEM_RESET        = 0x00080000,
		MEM_RESET_UNDO   = 0x1000000,
		MEM_LARGE_PAGES  = 0x20000000,
		MEM_PHYSICAL     = 0x00400000,
		MEM_TOP_DOWN     = 0x00100000,
		MEM_DECOMMIT     = 0x00004000,
		MEM_RELEASE		 = 0x00008000
	}

	public enum PAGE_PROTECT : uint
	{
		 PAGE_NOACCESS							=  0x01,    
		 PAGE_READONLY							=  0x02,    
		 PAGE_READWRITE							=  0x04,    
		 PAGE_WRITECOPY							=  0x08,    
		 PAGE_EXECUTE							=  0x10,    
		 PAGE_EXECUTE_READ						=  0x20,    
		 PAGE_EXECUTE_READWRITE					=  0x40,    
		 PAGE_EXECUTE_WRITECOPY					=  0x80,    
		 PAGE_GUARD								= 0x100,    
		 PAGE_NOCACHE							= 0x200,    
		 PAGE_WRITECOMBINE						= 0x400,    
		 PAGE_GRAPHICS_NOACCESS					= 0x0800,   
		 PAGE_GRAPHICS_READONLY					= 0x1000,   
		 PAGE_GRAPHICS_READWRITE				= 0x2000,   
		 PAGE_GRAPHICS_EXECUTE					= 0x4000,   
		 PAGE_GRAPHICS_EXECUTE_READ				= 0x8000,   
		 PAGE_GRAPHICS_EXECUTE_READWRITE		= 0x10000,    
		 PAGE_GRAPHICS_COHERENT					= 0x20000,    
		 PAGE_GRAPHICS_NOCACHE					= 0x40000,    
		 PAGE_ENCLAVE_THREAD_CONTROL		    = 0x80000000,  
		 PAGE_REVERT_TO_FILE_MAP			    = 0x80000000,  
		 PAGE_TARGETS_NO_UPDATE				    = 0x40000000,  
		 PAGE_TARGETS_INVALID				    = 0x40000000,  
		 PAGE_ENCLAVE_UNVALIDATED			    = 0x20000000,  
		 PAGE_ENCLAVE_MASK					    = 0x10000000,  
		 PAGE_ENCLAVE_DECOMMIT				    = (PAGE_ENCLAVE_MASK | 0), 
		 PAGE_ENCLAVE_SS_FIRST				    = (PAGE_ENCLAVE_MASK | 1), 
		 PAGE_ENCLAVE_SS_REST				    = (PAGE_ENCLAVE_MASK | 2)
	}

}
